<!doctype html>
<html lang="zh-CN">
<head>
  <base href="https://www.nodeapp.cn/modules.html" />
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>模块（Modules） | Node.js 中文文档 | Node.js 中文网</title>
  <meta name="description" content="Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型，使其轻量又高效。Node.js 的包管理器 npm，是全球最大的开源库生态系统。">
  <link rel="stylesheet" href="assets/style.css">
  <link rel="stylesheet" href="assets/sh.css">
  <link rel="canonical" href="https://www.nodeapp.cn/modules.html">
  <link rel="apple-touch-icon" href="apple-touch-icon.png">
  <link rel="icon" sizes="32x32" type="image/png" href="favicon.png">
  
  <script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?acdf78480f7f8f2b23b812565a5868e0";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>

</head>
<body class="alt apidoc" id="api-section-modules">
  <div id="content" class="clearfix">
    <div id="column1" data-id="modules" class="interior">
      <header>
        <h1>Node.js v8.x 中文文档</h1>
        <hr>
      </header>

      <div id="toc">
        <h2>目录</h2>
        <ul>
<li><span class="stability_2"><a href="#modules_modules">module (模块)</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_accessing_the_main_module">访问主模块</a></span></li>
<li><span class="stability_undefined"><a href="#modules_addenda_package_manager_tips">附录：包管理器的技巧</a></span></li>
<li><span class="stability_undefined"><a href="#modules_all_together">总结</a></span></li>
<li><span class="stability_undefined"><a href="#modules_caching">缓存</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_module_caching_caveats">模块缓存的注意事项</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#modules_core_modules">核心模块</a></span></li>
<li><span class="stability_undefined"><a href="#modules_cycles">循环</a></span></li>
<li><span class="stability_undefined"><a href="#modules_file_modules">文件模块</a></span></li>
<li><span class="stability_undefined"><a href="#modules_folders_as_modules">目录作为模块</a></span></li>
<li><span class="stability_undefined"><a href="#modules_loading_from_node_modules_folders">从 <code>node_modules</code> 目录加载</a></span></li>
<li><span class="stability_undefined"><a href="#modules_loading_from_the_global_folders">从全局目录加载</a></span></li>
<li><span class="stability_undefined"><a href="#modules_the_module_wrapper">模块包装器</a></span></li>
<li><span class="stability_undefined"><a href="#modules_the_module_scope">The module scope</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_dirname">__dirname</a></span></li>
<li><span class="stability_undefined"><a href="#modules_filename">__filename</a></span></li>
<li><span class="stability_undefined"><a href="#modules_exports">exports</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module">module</a></span></li>
<li><span class="stability_undefined"><a href="#modules_require">require()</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_require_cache">require.cache</a></span></li>
<li><span class="stability_0"><a href="#modules_require_extensions">require.extensions</a></span></li>
<li><span class="stability_undefined"><a href="#modules_require_resolve_request_options">require.resolve(request[, options])</a></span></li>
<li><span class="stability_undefined"><a href="#modules_require_resolve_paths_request">require.resolve.paths(request)</a></span></li>
</ul>
</li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#modules_the_module_object">module 对象</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_module_children">module.children</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_exports">module.exports</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_exports_shortcut">exports 快捷方式</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#modules_module_filename">module.filename</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_id">module.id</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_loaded">module.loaded</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_parent">module.parent</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_paths">module.paths</a></span></li>
<li><span class="stability_undefined"><a href="#modules_module_require_id">module.require(id)</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#modules_the_module_object_1">The <code>Module</code> Object</a></span><ul>
<li><span class="stability_undefined"><a href="#modules_module_builtinmodules">module.builtinModules</a></span></li>
</ul>
</li>
</ul>
</li>
</ul>

      </div>
<div id="apicontent">
        <h1>module (模块)<span><a class="mark" href="#modules_modules" id="modules_modules">#</a></span></h1>
<!--introduced_in=v0.10.0-->
<div class="api_stability api_stability_2"><a href="documentation.html#documentation_stability_index">稳定性: 2</a> - 稳定的</div><!--name=module-->
<p>在 Node.js 模块系统中，每个文件都被视为独立的模块。</p>
<p>例子，假设有一个名为 <code>foo.js</code> 的文件：</p>
<pre><code class="lang-js">const circle = require(&apos;./circle.js&apos;);
console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
</code></pre>
<p>在第一行中，<code>foo.js</code> 加载了同一目录下的 <code>circle.js</code> 模块。</p>
<p><code>circle.js</code> 文件的内容为：</p>
<pre><code class="lang-js">const { PI } = Math;

exports.area = (r) =&gt; PI * r ** 2;

exports.circumference = (r) =&gt; 2 * PI * r;
</code></pre>
<p><code>circle.js</code> 模块导出了 <code>area()</code> 和 <code>circumference()</code> 两个函数。
通过在特殊的 <code>exports</code> 对象上指定额外的属性，函数和对象可以被添加到模块的根部。</p>
<p>模块内的本地变量是私有的，因为模块被 Node.js 包装在一个函数中（详见<a href="#modules_the_module_wrapper">模块包装器</a>）。
在这个例子中，变量 <code>PI</code> 是 <code>circle.js</code> 私有的。</p>
<p><code>module.exports</code>属性可以被赋予一个新的值（例如函数或对象）。</p>
<p>如下，<code>bar.js</code> 会用到 <code>square</code> 模块，<code>square</code> 模块导出了 <code>Square</code> 类：</p>
<pre><code class="lang-js">const Square  = require(&apos;./square.js&apos;);
const mySquare = new Square(2);
console.log(`mySquare 的面积是 ${mySquare.area()}`);
</code></pre>
<p><code>square</code> 模块定义在 <code>square.js</code> 中：</p>
<pre><code class="lang-js">// 赋值给 `exports` 不会修改模块，必须使用 `module.exports`
module.exports = class Square {
  constructor(width) {
    this.width = width;
  }

  area() {
    return this.width ** 2;
  }
};

模块系统在 `require(&apos;module&apos;)` 模块中实现。
</code></pre>
<h2>访问主模块<span><a class="mark" href="#modules_accessing_the_main_module" id="modules_accessing_the_main_module">#</a></span></h2>
<!-- type=misc -->
<p>当 Node.js 直接运行一个文件时，<code>require.main</code> 会被设为它的 <code>module</code>。
这意味着可以通过 <code>require.main === module</code> 来判断一个文件是否被直接运行：</p>
<p>对于 <code>foo.js</code> 文件，如果通过 <code>node foo.js</code> 运行则为 <code>true</code>，但如果通过 <code>require(&apos;./foo&apos;)</code> 运行则为 <code>false</code>。</p>
<p>因为 <code>module</code> 提供了一个 <code>filename</code> 属性（通常等同于 <code>__filename</code>），所以可以通过检查 <code>require.main.filename</code> 来获取当前应用程序的入口点。</p>
<h2>附录：包管理器的技巧<span><a class="mark" href="#modules_addenda_package_manager_tips" id="modules_addenda_package_manager_tips">#</a></span></h2>
<!-- type=misc -->
<p>Node.js 的 <code>require()</code> 函数的语义被设计得足够通用化，可以支持许多合理的目录结构。
包管理器程序（如 <code>dpkg</code>、<code>rpm</code> 和 <code>npm</code>）可以不用修改就能够从 Node.js 模块构建本地包。</p>
<p>以下是一个推荐的目录结构：</p>
<p>假设想要在 <code>/usr/lib/node/&lt;some-package&gt;/&lt;some-version&gt;</code> 目录中保存一个特定版本的包的内容。</p>
<p>包可以依赖于其他包。
为了安装包 <code>foo</code>，可能需要安装一个指定版本的 <code>bar</code> 包。
<code>bar</code> 包也可能有依赖，且在某些情况下，依赖可能有冲突或形成循环。</p>
<p>因为 Node.js 会查找它所加载的模块的实际路径（也就是说会解析符号链接），然后在 <code>node_modules</code> 目录中寻找它们的依赖，<a href="#modules_loading_from_node_modules_folders">如下所述</a>，这种情况使用以下体系结构很容易解决：</p>
<ul>
<li><code>/usr/lib/node/foo/1.2.3/</code> - <code>foo</code> 包的内容，版本 1.2.3。</li>
<li><code>/usr/lib/node/bar/4.3.2/</code> - <code>foo</code> 依赖的 <code>bar</code> 包的内容。</li>
<li><code>/usr/lib/node/foo/1.2.3/node_modules/bar</code> - <code>/usr/lib/node/bar/4.3.2/</code> 的符号链接。</li>
<li><code>/usr/lib/node/bar/4.3.2/node_modules/*</code> - <code>bar</code> 所依赖的包的符号链接</li>
</ul>
<p>因此，即便存在循环依赖或依赖冲突，每个模块还是可以获得它所依赖的包的一个可用版本。</p>
<p>当 <code>foo</code> 包中的代码调用 <code>require(&apos;bar&apos;)</code>，它会获得符号链接 <code>/usr/lib/node/foo/1.2.3/node_modules/bar</code> 指向的版本。
然后，当 <code>bar</code> 包中的代码调用 <code>require(&apos;queue&apos;)</code>，它会获得符号链接 <code>/usr/lib/node/bar/4.3.2/node_modules/quux</code> 指向的版本。</p>
<p>此外，为了进一步优化模块查找过程，不要将包直接放在 <code>/usr/lib/node</code> 目录中，而是将它们放在 <code>/usr/lib/node_modules/&lt;name&gt;/&lt;version&gt;</code> 目录中。
这样 Node.js 就不会在 <code>/usr/node_modules</code> 或 <code>/node_modules</code> 目录中查找缺失的依赖。</p>
<p>为了使模块在 Node.js 的 REPL 中可用，可能需要将 <code>/usr/lib/node_modules</code> 目录添加到 <code>$NODE_PATH</code> 环境变量中。
由于在 <code>node_modules</code> 目录中查找模块使用的是相对路径，而调用 <code>require()</code> 的文件是基于实际路径的，因此包本身可以放在任何地方。</p>
<h2>总结<span><a class="mark" href="#modules_all_together" id="modules_all_together">#</a></span></h2>
<!-- type=misc -->
<p>想要获得调用 <code>require()</code> 时加载的确切的文件名，使用 <code>require.resolve()</code> 函数。</p>
<p>综上所述，以下用伪代码描述的高级算法，解释 <code>require.resolve()</code> 做了些什么：</p>
<pre><code class="lang-txt">从 Y 路径的模块 require(X)
1. 如果 X 是一个核心模块，
   a. 返回核心模块
   b. 结束
2. 如果 X 是以 &apos;/&apos; 开头
   a. 设 Y 为文件系统根目录
3. 如果 X 是以 &apos;./&apos; 或 &apos;/&apos; 或 &apos;../&apos; 开头
   a. 加载文件(Y + X)
   b. 加载目录(Y + X)
4. 加载Node模块(X, dirname(Y))
5. 抛出 &quot;未找到&quot;

加载文件(X)
1. 如果 X 是一个文件，加载 X 作为 JavaScript 文本。结束
2. 如果 X.js 是一个文件，加载 X.js 作为 JavaScript 文本。结束
3. 如果 X.json 是一个文件，解析 X.json 成一个 JavaScript 对象。结束
4. 如果 X.node 是一个文件，加载 X.node 作为二进制插件。结束

加载索引(X)
1. 如果 X/index.js 是一个文件，加载 X/index.js 作为 JavaScript 文本。结束
3. 如果 X/index.json  是一个文件，解析 X/index.json 成一个 JavaScript 对象。结束
4. 如果 X/index.node 是一个文件，加载 X/index.node 作为二进制插件。结束

加载目录(X)
1. 如果 X/package.json 是一个文件，
   a. 解析 X/package.json，查找 &quot;main&quot; 字段
   b. let M = X + (json main 字段)
   c. 加载文件(M)
   d. 加载索引(M)
2. 加载索引(X)

加载Node模块(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. 加载文件(DIR/X)
   b. 加载目录(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I &gt;= 0,
   a. if PARTS[I] = &quot;node_modules&quot; CONTINUE
   b. DIR = path join(PARTS[0 .. I] + &quot;node_modules&quot;)
   c. DIRS = DIRS + DIR
   d. let I = I - 1
5. return DIRS
</code></pre>
<h2>缓存<span><a class="mark" href="#modules_caching" id="modules_caching">#</a></span></h2>
<!--type=misc-->
<p>模块在第一次加载后会被缓存。
这也意味着（类似其他缓存机制）如果每次调用 <code>require(&apos;foo&apos;)</code> 都解析到同一文件，则返回相同的对象。</p>
<p>多次调用 <code>require(foo)</code> 不会导致模块的代码被执行多次。
这是一个重要的特性。
借助它, 可以返回“部分完成”的对象，从而允许加载依赖的依赖, 即使它们会导致循环依赖。</p>
<p>如果想要多次执行一个模块，可以导出一个函数，然后调用该函数。</p>
<h3>模块缓存的注意事项<span><a class="mark" href="#modules_module_caching_caveats" id="modules_module_caching_caveats">#</a></span></h3>
<!--type=misc-->
<p>模块是基于其解析的文件名进行缓存的。
由于调用模块的位置的不同，模块可能被解析成不同的文件名（比如从 <code>node_modules</code> 目录加载），这样就不能保证 <code>require(&apos;foo&apos;)</code> 总能返回完全相同的对象。</p>
<p>此外，在不区分大小写的文件系统或操作系统中，被解析成不同的文件名可以指向同一文件，但缓存仍然会将它们视为不同的模块，并多次重新加载。
例如，<code>require(&apos;./foo&apos;)</code> 和 <code>require(&apos;./FOO&apos;)</code> 返回两个不同的对象，而不会管 <code>./foo</code> 和 <code>./FOO</code> 是否是相同的文件。</p>
<h2>核心模块<span><a class="mark" href="#modules_core_modules" id="modules_core_modules">#</a></span></h2>
<!--type=misc-->
<p>Node.js 有些模块会被编译成二进制。
这些模块别的地方有更详细的描述。</p>
<p>核心模块定义在 Node.js 源代码的 <code>lib/</code> 目录下。</p>
<p><code>require()</code> 总是会优先加载核心模块。
例如，<code>require(&apos;http&apos;)</code> 始终返回内置的 HTTP 模块，即使有同名文件。</p>
<h2>循环<span><a class="mark" href="#modules_cycles" id="modules_cycles">#</a></span></h2>
<!--type=misc-->
<p>当循环调用 <code>require()</code> 时，一个模块可能在未完成执行时被返回。</p>
<p>例如以下情况:</p>
<p><code>a.js</code>:</p>
<pre><code class="lang-js">console.log(&apos;a 开始&apos;);
exports.done = false;
const b = require(&apos;./b.js&apos;);
console.log(&apos;在 a 中，b.done = %j&apos;, b.done);
exports.done = true;
console.log(&apos;a 结束&apos;);
</code></pre>
<p><code>b.js</code>:</p>
<pre><code class="lang-js">console.log(&apos;b 开始&apos;);
exports.done = false;
const a = require(&apos;./a.js&apos;);
console.log(&apos;在 b 中，a.done = %j&apos;, a.done);
exports.done = true;
console.log(&apos;b 结束&apos;);
</code></pre>
<p><code>main.js</code>:</p>
<pre><code class="lang-js">console.log(&apos;main 开始&apos;);
const a = require(&apos;./a.js&apos;);
const b = require(&apos;./b.js&apos;);
console.log(&apos;在 main 中，a.done=%j，b.done=%j&apos;, a.done, b.done);
</code></pre>
<p>当 <code>main.js</code> 加载 <code>a.js</code> 时，<code>a.js</code> 又加载 <code>b.js</code>。
此时，<code>b.js</code> 会尝试去加载 <code>a.js</code>。
为了防止无限的循环，会返回一个 <code>a.js</code> 的 <code>exports</code> 对象的 <strong>未完成的副本</strong> 给 <code>b.js</code> 模块。
然后 <code>b.js</code> 完成加载，并将 <code>exports</code> 对象提供给 <code>a.js</code> 模块。</p>
<p>当 <code>main.js</code> 加载这两个模块时，它们都已经完成加载。
因此，该程序的输出会是：</p>
<pre><code class="lang-txt">$ node main.js
main 开始
a 开始
b 开始
在 b 中，a.done = false
b 结束
在 a 中，b.done = true
a 结束
在 main 中，a.done=true，b.done=true
</code></pre>
<p>需要仔细的规划, 以允许循环模块依赖在应用程序内正常工作.</p>
<h2>文件模块<span><a class="mark" href="#modules_file_modules" id="modules_file_modules">#</a></span></h2>
<!--type=misc-->
<p>如果按确切的文件名没有找到模块，则 Node.js 会尝试带上 <code>.js</code>、<code>.json</code> 或 <code>.node</code> 拓展名再加载。</p>
<p><code>.js</code> 文件会被解析为 JavaScript 文本文件，<code>.json</code> 文件会被解析为 JSON 文本文件。
<code>.node</code> 文件会被解析为通过 <code>dlopen</code> 加载的编译后的插件模块。</p>
<p>以 <code>&apos;/&apos;</code> 为前缀的模块是文件的绝对路径。
例如，<code>require(&apos;/home/marco/foo.js&apos;)</code> 会加载 <code>/home/marco/foo.js</code> 文件。</p>
<p>以 <code>&apos;./&apos;</code> 为前缀的模块是相对于调用 <code>require()</code> 的文件的。
也就是说，<code>circle.js</code> 必须和 <code>foo.js</code> 在同一目录下以便于 <code>require(&apos;./circle&apos;)</code> 找到它。</p>
<p>当没有以 <code>&apos;/&apos;</code>、<code>&apos;./&apos;</code> 或 <code>&apos;../&apos;</code> 开头来表示文件时，这个模块必须是一个核心模块或加载自 <code>node_modules</code> 目录。</p>
<p>如果给定的路径不存在，则 <code>require()</code> 会抛出一个 <code>code</code> 属性为 <code>&apos;MODULE_NOT_FOUND&apos;</code> 的 <a href="errors.html#errors_class_error"><code>Error</code></a>。</p>
<h2>目录作为模块<span><a class="mark" href="#modules_folders_as_modules" id="modules_folders_as_modules">#</a></span></h2>
<!--type=misc-->
<p>可以把程序和库放到一个单独的目录，然后提供一个单一的入口来指向它。
把目录递给 <code>require()</code> 作为一个参数，有三种方式。</p>
<p>第一种方式是在根目录下创建一个 <code>package.json</code> 文件，并指定一个 <code>main</code> 模块。
例子，<code>package.json</code> 文件类似：</p>
<pre><code class="lang-json">{ &quot;name&quot; : &quot;some-library&quot;,
  &quot;main&quot; : &quot;./lib/some-library.js&quot; }
</code></pre>
<p>如果这是在 <code>./some-library</code> 目录中，则 <code>require(&apos;./some-library&apos;)</code> 会试图加载 <code>./some-library/lib/some-library.js</code>。</p>
<p>这就是 Node.js 处理 <code>package.json</code> 文件的方式。</p>
<p>注意：如果 <code>package.json</code> 中 <code>&quot;main&quot;</code> 入口指定的文件不存在，则无法解析，Node.js 会将模块视为不存在，并抛出默认错误：</p>
<pre><code class="lang-txt">Error: Cannot find module &apos;some-library&apos;
</code></pre>
<p>如果目录里没有 <code>package.json</code> 文件，则 Node.js 就会试图加载目录下的 <code>index.js</code> 或 <code>index.node</code> 文件。
例如，如果上面的例子中没有 <code>package.json</code> 文件，则 <code>require(&apos;./some-library&apos;)</code> 会试图加载：</p>
<ul>
<li><code>./some-library/index.js</code></li>
<li><code>./some-library/index.node</code></li>
</ul>
<h2>从 <code>node_modules</code> 目录加载<span><a class="mark" href="#modules_loading_from_node_modules_folders" id="modules_loading_from_node_modules_folders">#</a></span></h2>
<!--type=misc-->
<p>如果传递给 <code>require()</code> 的模块标识符不是一个<a href="#modules_core_modules">核心模块</a>，也没有以 <code>&apos;/&apos;</code> 、 <code>&apos;../&apos;</code> 或 <code>&apos;./&apos;</code> 开头，则 Node.js 会从当前模块的父目录开始，尝试从它的 <code>/node_modules</code> 目录里加载模块。
Node.js 不会附加 <code>node_modules</code> 到一个已经以 <code>node_modules</code> 结尾的路径上。</p>
<p>如果还是没有找到，则移动到再上一层父目录，直到文件系统的根目录。</p>
<p>例子，如果在 <code>&apos;/home/ry/projects/foo.js&apos;</code> 文件里调用了 <code>require(&apos;bar.js&apos;)</code>，则 Node.js 会按以下顺序查找：</p>
<ul>
<li><code>/home/ry/projects/node_modules/bar.js</code></li>
<li><code>/home/ry/node_modules/bar.js</code></li>
<li><code>/home/node_modules/bar.js</code></li>
<li><code>/node_modules/bar.js</code></li>
</ul>
<p>这使得程序本地化它们的依赖，避免它们产生冲突。</p>
<p>通过在模块名后包含一个路径后缀，可以请求特定的文件或分布式的子模块。
例如，<code>require(&apos;example-module/path/to/file&apos;)</code> 会把 <code>path/to/file</code> 解析成相对于 <code>example-module</code> 的位置。
后缀路径同样遵循模块的解析语法。</p>
<h2>从全局目录加载<span><a class="mark" href="#modules_loading_from_the_global_folders" id="modules_loading_from_the_global_folders">#</a></span></h2>
<!-- type=misc -->
<p>如果 <code>NODE_PATH</code> 环境变量被设为一个以冒号分割的绝对路径列表，则当在其他地方找不到模块时 Node.js 会搜索这些路径。</p>
<p>注意：在 Windows 系统中，<code>NODE_PATH</code> 是以分号间隔的。</p>
<p>在当前的<a href="#modules_all_together">模块解析</a>算法运行之前，<code>NODE_PATH</code> 最初是创建来支持从不同路径加载模块的。</p>
<p>虽然 <code>NODE_PATH</code> 仍然被支持，但现在不太需要，因为 Node.js 生态系统已制定了一套存放依赖模块的约定。
有时当人们没意识到 <code>NODE_PATH</code> 必须被设置时，依赖 <code>NODE_PATH</code> 的部署会出现意料之外的行为。
有时一个模块的依赖会改变，导致在搜索 <code>NODE_PATH</code> 时加载了不同的版本（甚至不同的模块）。</p>
<p>此外，Node.js 还会搜索以下位置：</p>
<ul>
<li>1: <code>$HOME/.node_modules</code></li>
<li>2: <code>$HOME/.node_libraries</code></li>
<li>3: <code>$PREFIX/lib/node</code></li>
</ul>
<p>其中 <code>$HOME</code> 是用户的主目录，<code>$PREFIX</code> 是 Node.js 里配置的 <code>node_prefix</code>。</p>
<p>这些主要是历史原因。</p>
<p>注意：强烈建议将所有的依赖放在本地的 <code>node_modules</code> 目录。
这样将会更快地加载，且更可靠。</p>
<h2>模块包装器<span><a class="mark" href="#modules_the_module_wrapper" id="modules_the_module_wrapper">#</a></span></h2>
<!-- type=misc -->
<p>在执行模块代码之前，Node.js 会使用一个如下的函数包装器将其包装：</p>
<pre><code class="lang-js">(function(exports, require, module, __filename, __dirname) {
// 模块的代码实际上在这里
});
</code></pre>
<p>通过这样做，Node.js 实现了以下几点：</p>
<ul>
<li>它保持了顶层的变量（用 <code>var</code>、<code>const</code> 或 <code>let</code> 定义）作用在模块范围内，而不是全局对象。</li>
<li>它有助于提供一些看似全局的但实际上是模块特定的变量，例如：<ul>
<li>实现者可以用于从模块中导出值的 <code>module</code> 和 <code>exports</code> 对象。</li>
<li>包含模块绝对文件名和目录路径的快捷变量 <code>__filename</code> 和 <code>__dirname</code> 。</li>
</ul>
</li>
</ul>
<h2>The module scope<span><a class="mark" href="#modules_the_module_scope" id="modules_the_module_scope">#</a></span></h2>
<h3>__dirname<span><a class="mark" href="#modules_dirname" id="modules_dirname">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.27</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a><!-- type=var -->
当前模块的文件夹名称。等同于 <a href="#modules_filename"><code>__filename</code></a> 的 <a href="path.html#path_path_dirname_path"><code>path.dirname()</code></a> 的值。</li>
</ul>
<!--
The directory name of the current module. This the same as the
[`path.dirname()`][] of the [`__filename`][].
-->
<p>示例：运行位于 <code>/Users/mjr</code>目录下的example.js文件：<code>node example.js</code>
<!--Example: running `node example.js` from `/Users/mjr`--></p>
<pre><code class="lang-js">console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
</code></pre>
<h3>__filename<span><a class="mark" href="#modules_filename" id="modules_filename">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.0.1</span>
</div><!-- type=var -->
<ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a></li>
</ul>
<p>当前模块的文件名称---解析后的绝对路径。</p>
<p>在主程序中这不一定要跟命令行中使用的名称一致。</p>
<p>参阅 <a href="#modules_dirname"><code>__dirname</code></a> 以获取当前模块的目录名称。</p>
<p>例如：</p>
<p>在 <code>/Users/mjr</code> 目录下执行 <code>node example.js</code> </p>
<pre><code class="lang-js">console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr
</code></pre>
<p>给定两个模块： <code>a</code> 和 <code>b</code>, 其中 <code>b</code> 是 <code>a</code> 的一个依赖。</p>
<p>文件目录结构如下：</p>
<ul>
<li><code>/Users/mjr/app/a.js</code></li>
<li><code>/Users/mjr/app/node_modules/b/b.js</code></li>
</ul>
<p><code>b.js</code> 中对 <code>__filename</code> 的引用将会返回 <code>/Users/mjr/app/node_modules/b/b.js</code>
<code>a.js</code> 中对 <code>__filename</code> 的引用将会返回 <code>/Users/mjr/app/a.js</code></p>
<h3>exports<span><a class="mark" href="#modules_exports" id="modules_exports">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.12</span>
</div><!-- type=var -->
<p>这是一个对于 <code>module.exports</code> 的更简短的引用形式。查看关于<a href="#modules_exports_shortcut">exports shortcut</a>的章节，详细了解什么时候使用<code>exports</code>、什么时候使用<code>module.exports</code>。</p>
<h3>module<span><a class="mark" href="#modules_module" id="modules_module">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><!-- type=var -->
<ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p>对当前模块的引用, 查看关于 <a href="#modules_the_module_object"><code>module</code> object</a> 的章节。 <code>module.exports</code> 用于指定一个模块所导出的内容，即可以通过 <code>require()</code> 访问的内容。</p>
<h3>require()<span><a class="mark" href="#modules_require" id="modules_require">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.13</span>
</div><!-- type=var -->
<ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&lt;Function&gt;</a></li>
</ul>
<p>引入模块.</p>
<h4>require.cache<span><a class="mark" href="#modules_require_cache" id="modules_require_cache">#</a></span></h4>
<div class="api_metadata">
<span>新增于: v0.3.0</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p>被引入的模块将被缓存在这个对象中。从此对象中删除键值对将会导致下一次 <code>require</code> 重新加载被删除的模块。注意不能删除 <a href="addons.html">native addons</a>（原生插件），因为它们的重载将会导致错误。</p>
<h4>require.extensions<span><a class="mark" href="#modules_require_extensions" id="modules_require_extensions">#</a></span></h4>
<div class="api_metadata">
<span>新增于: v0.3.0</span><span>废弃于: v0.10.6</span>
</div><div class="api_stability api_stability_0"><a href="documentation.html#documentation_stability_index">稳定性: 0</a> - 废弃的</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p>指示 <code>require</code> 怎样处理特定的文件扩展名</p>
<p>例如：把 <code>.sjs</code> 文件当做 <code>.js</code> 文件处理：</p>
<pre><code class="lang-js">require.extensions[&apos;.sjs&apos;] = require.extensions[&apos;.js&apos;];
</code></pre>
<p><strong>废弃的</strong>  以前这被用来将非 JavaScript 模块按需编译后加载到 Node.js 中。
然而，在实践中，有更多更好的解决方案，比如用其它 Node.js 程序加载模块，
或者提前将它们编译为 JavaScript 模块。</p>
<p>由于模块系统已锁定，这个特性可能永远不会消失，但是鉴于其复杂性和可能导致的小问题，
最好不要碰它。</p>
<p>模块系统把一个 <code>require(...)</code> 解析为文件名的操作数随着新注册文件扩展名的增加
呈线性递增。</p>
<p>也就是说，增加文件扩展名数量降低了模块导入的速度，这不应该被提倡。</p>
<h4>require.resolve(request[, options])<span><a class="mark" href="#modules_require_resolve_request_options" id="modules_require_resolve_request_options">#</a></span></h4>
<div class="api_metadata">
<details class="changelog"><summary>版本历史</summary>
<table>
<tbody><tr><th>版本</th><th>变更</th></tr>
<tr><td>v8.9.0</td>
<td><p>The <code>paths</code> option is now supported.</p>
</td></tr>
<tr><td>v0.3.0</td>
<td><p><span>新增于: v0.3.0</span></p>
</td></tr>
</tbody></table>
</details>
</div><ul>
<li><code>request</code> 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a> 需要解析的模块路径。</li>
<li><code>options</code> 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a><ul>
<li><code>paths</code> 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">&lt;Array&gt;</a> 解析模块的起点路径。此参数存在时，将使用这些路径而非默认解析路径。
注意此数组中的每一个路径都被用作模块解析算法的起点，意味着 <code>node_modules</code> 层级将从这里开始查询。</li>
</ul>
</li>
<li>Returns: 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a></li>
</ul>
<p>使用内部的 <code>require()</code> 机制查询模块的位置,
此操作只返回解析后的文件名，不会加载该模块。</p>
<h4>require.resolve.paths(request)<span><a class="mark" href="#modules_require_resolve_paths_request" id="modules_require_resolve_paths_request">#</a></span></h4>
<div class="api_metadata">
<span>新增于: v8.9.0</span>
</div><ul>
<li><code>request</code> 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a> 被查询解析路径的模块的路径。</li>
<li>返回: 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">&lt;Array&gt;</a> | 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Null_type" class="type">&lt;null&gt;</a></li>
</ul>
<p>返回一个数组，其中包含解析 <code>request</code> 过程中被查询的路径。
如果 <code>request</code> 字符串指向核心模块（例如 <code>http</code> 或 <code>fs</code>），则返回 <code>null</code>。</p>
<h2>module 对象<span><a class="mark" href="#modules_the_module_object" id="modules_the_module_object">#</a></span></h2>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><!-- type=var -->
<!-- name=module -->
<ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p>在每个模块中，<code>module</code> 的自由变量是一个指向表示当前模块的对象的引用。
为了方便，<code>module.exports</code> 也可以通过全局模块的 <code>exports</code> 对象访问。
<code>module</code> 实际上不是全局的，而是每个模块本地的。</p>
<h3>module.children<span><a class="mark" href="#modules_module_children" id="modules_module_children">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">&lt;Array&gt;</a></li>
</ul>
<p>被该模块引用的模块对象。</p>
<h3>module.exports<span><a class="mark" href="#modules_module_exports" id="modules_module_exports">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p><code>module.exports</code> 对象是由模块系统创建的。
有时这是难以接受的；许多人希望他们的模块成为某个类的实例。
为了实现这个，需要将期望导出的对象赋值给 <code>module.exports</code>。
注意，将期望的对象赋值给 <code>exports</code> 会简单地重新绑定本地 <code>exports</code> 变量，这可能不是期望的。</p>
<p>例子，假设创建了一个名为 <code>a.js</code> 的模块：</p>
<pre><code class="lang-js">const EventEmitter = require(&apos;events&apos;);

module.exports = new EventEmitter();

// 处理一些工作，并在一段时间后从模块自身触发 &apos;ready&apos; 事件。
setTimeout(() =&gt; {
  module.exports.emit(&apos;ready&apos;);
}, 1000);
</code></pre>
<p>然后，在另一个文件中可以这么做：</p>
<pre><code class="lang-js">const a = require(&apos;./a&apos;);
a.on(&apos;ready&apos;, () =&gt; {
  console.log(&apos;模块 a 已准备好&apos;);
});
</code></pre>
<p>注意，对 <code>module.exports</code> 的赋值必须立即完成。
不能在任何回调中完成。
以下是无效的：</p>
<p>x.js:</p>
<pre><code class="lang-js">setTimeout(() =&gt; {
  module.exports = { a: &apos;hello&apos; };
}, 0);
</code></pre>
<p>y.js:</p>
<pre><code class="lang-js">const x = require(&apos;./x&apos;);
console.log(x.a);
</code></pre>
<h4>exports 快捷方式<span><a class="mark" href="#modules_exports_shortcut" id="modules_exports_shortcut">#</a></span></h4>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><p><code>exports</code> 变量是在模块的文件级别作用域内有效的，它在模块被执行前被赋予 <code>module.exports</code> 的值。</p>
<p>它有一个快捷方式，以便 <code>module.exports.f = ...</code> 可以被更简洁地写成 <code>exports.f = ...</code>。
注意，就像任何变量，如果一个新的值被赋值给 <code>exports</code>，它就不再绑定到 <code>module.exports</code>：</p>
<pre><code class="lang-js">module.exports.hello = true; // 从对模块的引用中导出
exports = { hello: false };  // 不导出，只在模块内有效
</code></pre>
<p>当 <code>module.exports</code> 属性被一个新的对象完全替代时，也会重新赋值 <code>exports</code>，例如：</p>
<!-- eslint-disable func-name-matching -->
<pre><code class="lang-js">module.exports = exports = function Constructor() {
  // ... 及其他
};
</code></pre>
<p>为了解释这个行为，想象对 <code>require()</code> 的假设实现，它跟 <code>require()</code> 的实际实现相当类似：</p>
<pre><code class="lang-js">function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) =&gt; {
    // 模块代码在这。在这个例子中，定义了一个函数。
    function someFunc() {}
    exports = someFunc;
    // 此时，exports 不再是一个 module.exports 的快捷方式，
    // 且这个模块依然导出一个空的默认对象。
    module.exports = someFunc;
    // 此时，该模块导出 someFunc，而不是默认对象。
  })(module, module.exports);
  return module.exports;
}
</code></pre>
<h3>module.filename<span><a class="mark" href="#modules_module_filename" id="modules_module_filename">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a></li>
</ul>
<p>模块的完全解析后的文件名。</p>
<h3>module.id<span><a class="mark" href="#modules_module_id" id="modules_module_id">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a></li>
</ul>
<p>模块的标识符。
通常是完全解析后的文件名。</p>
<h3>module.loaded<span><a class="mark" href="#modules_module_loaded" id="modules_module_loaded">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type" class="type">&lt;boolean&gt;</a></li>
</ul>
<p>模块是否已经加载完成，或正在加载中。</p>
<h3>module.parent<span><a class="mark" href="#modules_module_parent" id="modules_module_parent">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.1.16</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a> 模块对象</li>
</ul>
<p>最先引用该模块的模块。</p>
<h3>module.paths<span><a class="mark" href="#modules_module_paths" id="modules_module_paths">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.4.0</span>
</div><ul>
<li><span class="type">&lt;string []&gt;</span></li>
</ul>
<p>模块的搜索路径。</p>
<h3>module.require(id)<span><a class="mark" href="#modules_module_require_id" id="modules_module_require_id">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v0.5.1</span>
</div><ul>
<li><code>id</code> 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string&gt;</a></li>
<li>返回: 
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a> 已解析的模块的 <code>module.exports</code></li>
</ul>
<p><code>module.require</code> 方法提供了一种类似 <code>require()</code> 从原始模块被调用的加载模块的方式。</p>
<p>注意，为了做到这个，需要获得一个 <code>module</code> 对象的引用。
因为 <code>require()</code> 会返回 <code>module.exports</code>，且 <code>module</code> <strong>只</strong>在一个特定的模块代码中有效，所以为了使用它，必须明确地导出。</p>
<h2>The <code>Module</code> Object<span><a class="mark" href="#modules_the_module_object_1" id="modules_the_module_object_1">#</a></span></h2>
<div class="api_metadata">
<span>新增于: v0.3.7</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&lt;Object&gt;</a></li>
</ul>
<p>Provides general utility methods when interacting with instances of
<code>Module</code> -- the <code>module</code> variable often seen in file modules. Accessed
via <code>require(&apos;module&apos;)</code>.</p>
<h3>module.builtinModules<span><a class="mark" href="#modules_module_builtinmodules" id="modules_module_builtinmodules">#</a></span></h3>
<div class="api_metadata">
<span>新增于: v8.10.0</span>
</div><ul>
<li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&lt;string[]&gt;</a></li>
</ul>
<p>A list of  the names of all modules provided by Node.js. Can be used to verify
if a module is maintained by a third-party module or not.</p>

      </div>
    </div>

    <div id="column2" class="interior">
      <div id="intro" class="interior">
        <a href="/" title="Go back to the home page">
          Node.js 中文文档 | Node.js 中文网
        </a>
      </div>
      
        <!-- [start-include:_toc.md] -->
<ul>
<li><a href="documentation.html">关于本文档</a></li>
<li><a href="synopsis.html">用法与例子</a></li>
</ul>
<div class="line"></div>

<ul>
<li><a href="assert.html">断言测试</a></li>
<li><a href="async_hooks.html">异步钩子（Async Hooks）</a></li>
<li><a href="buffer.html">缓存（Buffer）</a></li>
<li><a href="addons.html">C++ 插件</a></li>
<li><a href="n-api.html">C/C++ 插件 - N-API</a></li>
<li><a href="child_process.html">子进程</a></li>
<li><a href="cluster.html">集群（Cluster）</a></li>
<li><a href="cli.html">命令行参数</a></li>
<li><a href="console.html">控制台（Console）</a></li>
<li><a href="crypto.html">加密（Crypto）</a></li>
<li><a href="debugger.html">调试器</a></li>
<li><a href="deprecations.html">废弃的 API</a></li>
<li><a href="dns.html">DNS</a></li>
<li><a href="domain.html">域（Domain）</a></li>
<li><a href="esm.html">ECMAScript 模块</a></li>
<li><a href="errors.html">错误（Errors）</a></li>
<li><a href="events.html">事件（Events）</a></li>
<li><a href="fs.html">文件系统</a></li>
<li><a href="globals.html">全局对象（Globals）</a></li>
<li><a href="http.html">HTTP</a></li>
<li><a href="http2.html">HTTP/2</a></li>
<li><a href="https.html">HTTPS</a></li>
<li><a href="inspector.html">检查工具（Inspector）</a></li>
<li><a href="intl.html">国际化</a></li>
<li><a href="modules.html">模块（Modules）</a></li>
<li><a href="net.html">网络（Net）</a></li>
<li><a href="os.html">操作系统（OS）</a></li>
<li><a href="path.html">路径（Path）</a></li>
<li><a href="perf_hooks.html">性能钩子（Performance Hooks）</a></li>
<li><a href="process.html">进程</a></li>
<li><a href="punycode.html">Punycode</a></li>
<li><a href="querystring.html">查询字符串</a></li>
<li><a href="readline.html">逐行读取</a></li>
<li><a href="repl.html">交互式解释器（REPL）</a></li>
<li><a href="stream.html">流（Stream）</a></li>
<li><a href="string_decoder.html">字符串解码</a></li>
<li><a href="timers.html">定时器（Timers）</a></li>
<li><a href="tls.html">安全传输层（TLS/SSL）</a></li>
<li><a href="tracing.html">事件跟踪（Tracing）</a></li>
<li><a href="tty.html">TTY</a></li>
<li><a href="dgram.html">UDP / 数据报</a></li>
<li><a href="url.html">URL</a></li>
<li><a href="util.html">工具集</a></li>
<li><a href="v8.html">V8</a></li>
<li><a href="vm.html">虚拟机（VM）</a></li>
<li><a href="zlib.html">压缩（ZLIB）</a></li>
</ul>
<div class="line"></div>

<ul>
<li><a href="https://github.com/nodejs/node">GitHub 仓库和问题跟踪</a></li>
<li><a href="https://groups.google.com/group/nodejs">邮件列表</a></li>
</ul>
<!-- [end-include:_toc.md] -->

      
    </div>
  </div>
  <script src="assets/sh_main.js"></script>
  <script src="assets/sh_javascript.min.js"></script>
  <script>highlight(undefined, undefined, 'pre');</script>
</body>
</html>
